﻿using Autofac;
using SharpDX.Windows;
using System;
using System.Windows.Forms;

namespace Ensemble_Windows
{
    /// <summary>
    /// 渲染基类
    /// </summary>
    public abstract class Direct
    {
        /// <summary>
        /// window控件承载
        /// </summary>
        public Form _form { get; set; }
        private readonly Time clock = new Time();
        private FormWindowState _currentFormWindowState { get; set; }
        private bool _disposed { get; set; }
        private float _frameAccumlator { get; set; }
        private int _frameCount { get; set; }
        private Configuration _configuration { get; set; }

        ~Direct()
        {
            if (!_disposed)
            {
                Dispose(false);
                _disposed = true;
            }
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                Dispose(true);
                _disposed = true;
            }
            GC.SuppressFinalize(this);

        }

        protected virtual void Dispose(bool disposeManagedResources)
        {
            if (disposeManagedResources)
            {
                if (_form != null)
                {
                    _form.Dispose();
                }
            }
        }

        /// <summary>
        /// 返回句柄显示
        /// </summary>
        protected IntPtr DisplayHandle
        {
            get { return _form.Handle; }
        }

        /// <summary>
        /// 获取配置
        /// </summary>
        public Configuration Config
        {
            get { return _configuration; }
        }

        /// <summary>
        /// 获取上次帧后传递的秒数
        /// </summary>
        public float FrameDelta { get; private set; }

        /// <summary>
        /// 获取上次帧后传递的秒数
        /// </summary>
        public float FramePerSecond { get; private set; }

        /// <summary>
        /// 创建窗体
        /// </summary>
        /// <param name="config">配置</param>
        /// <returns>渲染窗体</returns>
        protected virtual Form CreateForm(Configuration config)
        {
            return new RenderForm(config.Title)
            {
                ClientSize = new System.Drawing.Size(config.Width, config.Height)
            };
        }

        /// <summary>
        /// 运行窗体
        /// </summary>
        public void Run()
        {
            Run(new Configuration());
        }

        /// <summary>
        /// 运行窗体
        /// </summary>
        /// <param name="configuration">配置</param>
        public void Run(Configuration configuration)
        {
            _configuration = configuration ?? new Configuration();
            _form = CreateForm(_configuration);
            Initialize(configuration);

            bool isFormClosed = false;
            bool formIsResizeing = false;

            _form.MouseClick += HandleMouseClick;
            _form.KeyDown += HandleKeyDown;
            _form.FormBorderStyle = FormBorderStyle.FixedDialog;
            _form.MaximizeBox = false;
            //_form.Icon = new System.Drawing.Icon("favicon.ico");
            _form.KeyUp += HandleKeyUp;
            _form.Resize += (o, args) =>
            {
                if (_form.WindowState != _currentFormWindowState)
                {
                    HandleResize(o, args);
                }

                _currentFormWindowState = _form.WindowState;
            };

            _form.ResizeBegin += (o, args) => { formIsResizeing = true; };
            _form.ResizeEnd += (o, args) =>
            {
                formIsResizeing = false;
                HandleResize(o, args);
            };

            _form.Closed += (o, args) => { isFormClosed = true; };

            LoadContent();
            clock.Start();
            BeginRun();
            RenderLoop.Run(_form, () =>
            {
                if (isFormClosed)
                {
                    return;
                }

                OnUpdate();
                if (!formIsResizeing)
                {
                    Render();
                }
            });

            UnloadContent();
            EndRun();
        }

        /// <summary>
        /// 游戏初始化
        /// </summary>
        /// <param name="configuration">配置</param>
        protected abstract void Initialize(Configuration configuration);

        /// <summary>
        /// 加载资源
        /// </summary>
        protected virtual void LoadContent()
        { }

        /// <summary>
        /// 卸载资源
        /// </summary>
        protected virtual void UnloadContent()
        { }

        /// <summary>
        /// 游戏更新
        /// </summary>
        /// <param name="time">更新频率</param>
        protected virtual void Update(Time time)
        {
            GC.Collect();
        }

        /// <summary>
        /// 鼠标点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleMouseClick(object sender, MouseEventArgs e)
        {
            MouseClick(e);
        }

        /// <summary>
        /// 按键按下事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleKeyDown(object sender, KeyEventArgs e)
        {
            KeyDown(e);
        }

        /// <summary>
        /// 按键弹起事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleKeyUp(object sender, KeyEventArgs e)
        {
            KeyUp(e);
        }

        /// <summary>
        /// 窗体拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleResize(object sender, EventArgs e)
        {
            if (_form.WindowState == FormWindowState.Minimized)
            {
                return;
            }
        }

        /// <summary>
        /// 鼠标点击
        /// </summary>
        /// <param name="e"></param>
        protected virtual void MouseClick(MouseEventArgs e)
        {
        }

        /// <summary>
        /// 按键按下
        /// </summary>
        /// <param name="e"></param>
        protected virtual void KeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                Exit();
            }
        }

        /// <summary>
        /// 按键弹起
        /// </summary>
        /// <param name="e"></param>
        protected virtual void KeyUp(KeyEventArgs e)
        {
        }

        /// <summary>
        /// 游戏开始运行
        /// </summary>
        protected virtual void BeginRun()
        { }

        /// <summary>
        /// 游戏结束运行
        /// </summary>
        protected virtual void EndRun()
        { }

        /// <summary>
        /// 关闭窗体
        /// </summary>
        public void Exit()
        {
            _form.Close();
        }

        private void OnUpdate()
        {
            FrameDelta = (float)clock.Update();
            Update(clock);
        }

        private void Render()
        {
            _frameAccumlator += FrameDelta;
            ++_frameCount;
            if (_frameAccumlator >= 1.0f)
            {
                FramePerSecond = _frameCount / _frameAccumlator;

                _form.Text = _configuration.Title;
                _frameAccumlator = 0.0f;
                _frameCount = 0;
            }

            BeginDraw();
            Draw(clock);
            EndDraw();
        }

        /// <summary>
        /// 绘图
        /// </summary>
        /// <param name="time">绘图频率</param>
        protected virtual void Draw(Time time)
        { }

        /// <summary>
        /// 开始绘图
        /// </summary>
        protected virtual void BeginDraw()
        { }

        /// <summary>
        /// 结束绘图
        /// </summary>
        protected virtual void EndDraw()
        { }
    }
}
